package com.yx.accountBook.common.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.SerializeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by lichagnfeng on 2017/2/13.
 */
public class MyRedisSessionDao extends AbstractSessionDAO {
    private static Logger logger = LoggerFactory.getLogger(MyRedisSessionDao.class);
    private RedisManager redisManager;
    private String keyPrefix = "shiro_redis_session:";

    public MyRedisSessionDao() {
    }

    public void update(Session session) throws UnknownSessionException {
        this.saveSession(session);
    }

    private void saveSession(Session session) throws UnknownSessionException {
        logger.debug(" to saveSession");
        if(session != null && session.getId() != null) {
            byte[] key = this.getByteKey(session.getId());
            byte[] value = SerializeUtils.serialize(session);
            session.setTimeout((long)(this.redisManager.getExpire() * 1000));
            this.redisManager.set(key, value, this.redisManager.getExpire());
        } else {
            logger.error("session or session id is null");
        }
    }

    public void delete(Session session) {
        logger.debug(" to delete");

        if(session != null && session.getId() != null) {
            this.redisManager.del(this.getByteKey(session.getId()));
        } else {
            logger.error("session or session id is null");
        }
    }

    public Collection<Session> getActiveSessions() {
        logger.debug(" to getActiveSessions");
        HashSet sessions = new HashSet();
        Set keys = this.redisManager.keys(this.keyPrefix + "*");
        if(keys != null && keys.size() > 0) {
            Iterator i$ = keys.iterator();

            while(i$.hasNext()) {
                byte[] key = (byte[])i$.next();
                Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(key));
                sessions.add(s);
            }
        }

        return sessions;
    }

    protected Serializable doCreate(Session session) {
        logger.debug(" to doCreate");
        Serializable sessionId = this.generateSessionId(session);
        this.assignSessionId(session, sessionId);
        this.saveSession(session);
        return sessionId;
    }

    protected Session doReadSession(Serializable sessionId) {
        logger.debug(" to doReadSession:"+sessionId);
        if(sessionId == null) {
            logger.error("session id is null");
            return null;
        } else {
            //logger.debug(new String(this.redisManager.get(this.getByteKey(sessionId))));
            Session s = (Session)SerializeUtils.deserialize(this.redisManager.get(this.getByteKey(sessionId)));
            SimpleSession ss = (SimpleSession) s;
            /*Map hm = ss.getAttributes();

            SimplePrincipalCollection spc = null;
            if (hm!=null){
                spc = (SimplePrincipalCollection) hm.get("org.apache.shiro.Subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY");
            }*/

            //logger.debug(new JsonObject().);
            //"org.apache.shiro.Subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY" -> "lcf" "org.apache.shiro.Subject.support.DefaultSubjectContext_AUTHENTICATED_SESSION_KEY" -> "true"
            /*if (hm!=null&&hm.size()>0&&hm.get("org.apache.shiro.Subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY")==null){
                hm.put("org.apache.shiro.Subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY","lcf");
                hm.put("org.apache.shiro.Subject.support.DefaultSubjectContext_AUTHENTICATED_SESSION_KEY",true);
                ss.setHost("127.0.0.1");
                SimplePrincipalCollection spcc = new SimplePrincipalCollection();
                spcc.add();
                DelegatingSubject
                throw new RuntimeException("test");
            }*/
            return s;
        }
    }

    private byte[] getByteKey(Serializable sessionId) {

        //logger.debug(" to getByteKey");
        String preKey = this.keyPrefix + sessionId;
        return preKey.getBytes();
    }

    public RedisManager getRedisManager() {
        logger.debug(" to getRedisManager");
        return this.redisManager;
    }

    public void setRedisManager(RedisManager redisManager) {
        logger.debug(" to setRedisManager");
        this.redisManager = redisManager;
        this.redisManager.init();
    }

    public String getKeyPrefix() {
        logger.debug(" to getKeyPrefix");
        return this.keyPrefix;
    }

    public void setKeyPrefix(String keyPrefix) {
        logger.debug(" to setKeyPrefix");
        this.keyPrefix = keyPrefix;
    }
}